package net.cathackers.devel.scmp.impl;

import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;

import net.cathackers.devel.exceptions.CATException;
import net.cathackers.devel.scmp.exceptions.ServiceManagerNotFound;
import net.cathackers.devel.scmp.interfaces.CoreSwitch;
import net.cathackers.devel.scmp.interfaces.CoreSwitchBackend;
import net.cathackers.devel.scmp.interfaces.Envelope;
import net.cathackers.devel.scmp.interfaces.ServiceManager;
import net.cathackers.devel.scmp.interfaces.ServiceManagerInfo;

public class LocalCoreSwitch implements CoreSwitch {
    private Hashtable<String, ServiceManager> managers;
    private Hashtable<String, ServiceManagerInfo> names;
    private Vector<String> blacklistRequested;
    private CoreSwitchBackend backend;

    public LocalCoreSwitch(CoreSwitchBackend backend) {
	managers = new Hashtable<String, ServiceManager>();
	names = new Hashtable<String, ServiceManagerInfo>();
	blacklistRequested = new Vector<String>();
	this.backend = backend;
    }
    
    public LocalCoreSwitch(Map<String, ServiceManager> managers,
	    CoreSwitchBackend backend) {
	this.managers.putAll(managers);
	this.blacklistRequested = new Vector<String>();
	this.backend = backend;
    }

    @Override
    public String[] getAllServiceManagersGUIDs() {
	return (String[]) managers.keySet().toArray(new String[0]);
    }

    @Override
    public ServiceManager getServiceManagerByGUID(String GUID) {
	return managers.get(GUID);
    }

    @Override
    public void registerServiceManager(ServiceManager manager)
	    throws CATException {
	if (!managers.containsKey(manager.getGUID())) {
	    managers.put(manager.getGUID(), manager);
	    names.put(manager.getName(), manager);
	}
    }

    @Override
    public void requestBlacklistServiceManager(String GUID) {
	/*
	 * Better to implement Observer Design pattern here, so we can notify
	 * all whom it may concern. Or maybe a notification manager
	 */
	ServiceManager service = managers.get(GUID);
	if (service != null) {
	    blacklistRequested.add(service.getGUID());
	}

    }

    @Override
    public void unregisterServiceManager(String GUID) throws CATException {
	/*
	 * Add cross-cutting concern here (Permission Check) But this normally
	 * isn't needed because of the program logic.
	 */
	ServiceManager service = managers.get(GUID);
	if (service != null) {
	    names.remove(service.getName());
	    managers.remove(GUID);
	} else {
	    throw new ServiceManagerNotFound();
	}
    }

    @Override
    public boolean isBlacklistingRequested(String GUID) {
	return blacklistRequested.contains(GUID);
    }

    @Override
    public void routeEnvelope(Envelope message) throws CATException {
	ServiceManagerInfo target = message.getToServiceManager();
	String targetGUID = null;

	if (target.getGUID() != null) {
	    targetGUID = target.getGUID();
	} else if (target.getName() != null) {

	    targetGUID = names.get(target.getName()).getGUID();
	} else if (target.getServiceType() != null) {

	    // the slowest search...
	    for (ServiceManagerInfo service : names.values()) {
		if (service.getServiceType() == target.getServiceType()) {
		    targetGUID = service.getGUID();
		    break;
		}
	    }
	}

	if (targetGUID == null) {
	    throw new ServiceManagerNotFound();
	}
	managers.get(targetGUID).handle(message);
    }

    @Override
    public String[] getAllServiceManagersNames() {
	return (String[]) names.keySet().toArray(new String[0]);
    }

    @Override
    public ServiceManager getServiceManagerByName(String name)
	    throws ServiceManagerNotFound {

	ServiceManagerInfo service = names.get(name);
	if (service == null) {
	    throw new ServiceManagerNotFound();
	}
	return managers.get(service.getGUID());
    }
    
}
